package com.gzbd.login.shiro;

import com.gzbd.login.jwt.CustomTokenManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.util.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ObjectUtils;

import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 自定义session dao
 *
 * @author :ys
 * @date :2023-07-26 16:29
 */
public class CustomSessionDAO extends AbstractSessionDAO {

    private static final Logger logger = LoggerFactory.getLogger(CustomSessionDAO.class);

    /**
     * session 缓存 key:userId value:session object
     */
    private final Map<String, Session> sessions = new ConcurrentHashMap<>();

    /**
     * token缓存管理工具
     */
    private final CustomTokenManager customTokenManager;

    public CustomSessionDAO(CustomTokenManager customTokenManager) {
        this.customTokenManager = customTokenManager;
    }

    @Override
    protected Serializable doCreate(Session session) {
        String sessionId = (String) generateSessionId(session);
        Session oldSession = sessions.get(sessionId);
        if (!ObjectUtils.isEmpty(oldSession)) {
            try {
                Object tokenObj = oldSession.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
                if (!ObjectUtils.isEmpty(tokenObj)) {
                    customTokenManager.removeToken(tokenObj.toString());
                }
            } catch (Exception e) {
                logger.error("old session handle exception", e);
            }
        }
        sessions.put(sessionId, session);
        return sessionId;
    }

    @Override
    protected Session doReadSession(Serializable sessionId) {

        return sessions.get((String) sessionId);
    }

    @Override
    public void update(Session session) throws UnknownSessionException {
        doCreate(session);
    }

    @Override
    public void delete(Session session) {
        if (session == null) {
            throw new NullPointerException("session argument cannot be null.");
        }
        String sessionId = (String) generateSessionId(session);
        if (sessionId != null) {
            sessions.remove(sessionId);
        }
    }

    @Override
    public Collection<Session> getActiveSessions() {
        Collection<Session> values = sessions.values();
        if (CollectionUtils.isEmpty(values)) {
            return Collections.emptySet();
        } else {
            return Collections.unmodifiableCollection(values);
        }
    }
}
